package server

import (
	"container/list"
	"net/http"
	"sync"

	"git.oschina.net/ant180/gotesser/captcha"
	"git.oschina.net/ant180/gotesser/config"
	"git.oschina.net/ant180/gotesser/pub"
	"github.com/xlvector/dlog"
)

var gNewMap = map[string]pub.NewFunc{
	"baixing": captcha.NewBaixing,
}

type innerTesser struct {
	tessers *list.List
	lock    *sync.Mutex
}

func (p *innerTesser) Get() pub.CaptchaCoder {
	p.lock.Lock()
	defer p.lock.Unlock()

	e := p.tessers.Back()
	if e != nil {
		p.tessers.Remove(e)
		ret, ok := e.Value.(pub.CaptchaCoder)
		if ok {
			return ret
		}
		dlog.Warn("value is not CaptchaCoder")
	}

	return nil
}

func (p *innerTesser) Done(coder pub.CaptchaCoder) {
	p.lock.Lock()
	defer p.lock.Unlock()
	p.tessers.PushFront(coder)
}

type Server struct {
	conf   *config.Config
	tmlist map[string]innerTesser
}

func NewServer(conf *config.Config) *Server {
	s := &Server{
		conf:   conf,
		tmlist: make(map[string]innerTesser),
	}

	for k, v := range conf.Tessers {
		newFunc, ok := gNewMap[k]
		if !ok {
			dlog.Warn("not support %v", k)
			continue
		}

		innTsr := innerTesser{
			tessers: list.New(),
			lock:    new(sync.Mutex),
		}
		for i := 1; i < v; i++ {
			c, err := newFunc(0)
			if err != nil {
				dlog.Fatal("new captchacoder fail! %v", k)
			}

			innTsr.Done(c)
		}
		//至少存在一个
		c, err := newFunc(0)
		if err != nil {
			dlog.Fatal("new captchacoder fail! %v", k)
		}
		innTsr.Done(c)

		s.tmlist[k] = innTsr

	}

	return s
}

func (p *Server) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
	if "POST" != req.Method {
		return
	}
	req.ParseMultipartForm(4096)
	req.ParseForm()
	file, _, err := req.FormFile("pic")
	if err != nil {
		resp.Write([]byte("not found pic file!"))
		dlog.Warn("not found pic: %s", req.RemoteAddr)
		return
	}
	tmpl := req.FormValue("tmpl")
	intsr, ok := p.tmlist[tmpl]
	if !ok {
		resp.Write([]byte("not found tmpl!"))
		dlog.Warn("not found tmpl: %s %v", req.RemoteAddr, tmpl)
		return
	}

	/*
		img, err := ioutil.ReadAll(file)
		if err != nil {
			resp.Write([]byte("read pic fail!"))
			dlog.Warn("read pic fail: %s", req.RemoteAddr)
			return
		}
		code := req.FormValue("code")
		numCode, err := strconv.Atoi(code)
		if err != nil {
			resp.Write([]byte("code fail!"))
			dlog.Warn("code fail: %s", req.RemoteAddr)
			return
		}
		procIntf, ok := tesserHandles[numCode]
		if !ok {
			resp.Write([]byte("code not found!"))
			dlog.Warn("code not found: %s", req.RemoteAddr)
			return
		}
	*/

	//must Done after Get
	captchaCoder := intsr.Get()
	ret, err := captchaCoder.DecodeByReader(file)
	intsr.Done(captchaCoder)

	if err != nil {
		resp.Write([]byte("recognize fail!"))
		dlog.Warn("not found tmpl: %s %v", req.RemoteAddr, err)
		return
	}

	resp.Write([]byte(ret))
	return
}
